//
//  ViewController.swift
//  VideoPhotoCapture
//
//  Created by 杨伟诺 on 2020/9/23.
//

import UIKit
import AVFoundation
import Photos
import SnapKit

class ViewController: UIViewController {
    
    lazy var previewLayer: PreviewLayerView = PreviewLayerView()

    lazy var live: UISegmentedControl = {
        let sg = UISegmentedControl.init()
        sg.backgroundColor = UIColor.lightGray
        sg.insertSegment(withTitle: "LIVE", at: 0, animated: false)
        sg.insertSegment(withTitle: "Photo", at: 1, animated: false)
        sg.selectedSegmentIndex = 1
        sg.selectedSegmentTintColor = .white
        sg.tintColor = .black
        sg.addTarget(self, action: #selector(segmentChage), for: .valueChanged)
        return sg
    }()
    
    lazy var captureBtn: UIButton = {
        let b = UIButton()
        b.backgroundColor = UIColor.white
        b.layer.borderWidth = 3
        b.layer.masksToBounds = true
        b.layer.cornerRadius = 30
        b.layer.masksToBounds = true
        b.layer.borderColor = UIColor.lightGray.cgColor
        b.addTarget(self, action: #selector(captureClick), for: .touchUpInside)
        return b
    }()
    
    lazy var changeCameraBtn: UIButton = {
        let b = UIButton.init()
        b.setTitle("切换", for: .normal)
        b.addTarget(self, action: #selector(changeCamera), for: .touchUpInside)
        return b
    }()
    
    lazy var photoImageBtn: UIButton = {
        let b = UIButton()
        b.backgroundColor = .clear
        return b
    }()
    
    var windowOrientation: UIInterfaceOrientation {
        return view.window?.windowScene?.interfaceOrientation ?? .unknown
    }
    
    fileprivate var videCapture: VideoCaptureManager = VideoCaptureManager.manager

    private(set) var requestedPhotoSettings: AVCapturePhotoSettings = AVCapturePhotoSettings.init()
    
    private var photoData: Data?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .clear
        view.addSubview(previewLayer)
        previewLayer.snp.makeConstraints { (make) in
            make.width.height.centerX.centerY.equalToSuperview()
        }
        
        
        view.addSubview(live)
        live.snp.makeConstraints { (make) in
            make.centerX.equalToSuperview()
            make.width.equalTo(180)
            make.height.equalTo(30)
            make.top.equalTo(30)
        }
        view.addSubview(captureBtn)
        captureBtn.snp.makeConstraints { (make) in
            make.centerX.equalToSuperview()
            make.width.height.equalTo(60)
            make.bottom.equalTo(-10)
        }
        view.addSubview(changeCameraBtn)
        changeCameraBtn.snp.makeConstraints { (make) in
            make.width.height.equalTo(60)
            make.right.equalTo(-10)
            make.bottom.equalTo(-10)
        }
        view.addSubview(photoImageBtn)
        photoImageBtn.snp.makeConstraints { (make) in
            make.width.height.equalTo(60)
            make.left.equalTo(10)
            make.bottom.equalTo(-10)
        }
        previewLayer.session = videCapture.session
        
        videCapture.authorization()
        videCapture.configuragionSession {
            DispatchQueue.main.async {
                var videoOrientation : AVCaptureVideoOrientation = .portrait
                if self.windowOrientation != .unknown {
                    if let or = AVCaptureVideoOrientation.init(rawValue: self.windowOrientation.rawValue){
                        videoOrientation = or
                    }
                }
                self.previewLayer.videoPreviewLayer.connection?.videoOrientation = videoOrientation
            }
        }
    }

    override var shouldAutorotate: Bool{
        
        if videCapture.movieFileOutput?.isRecording ?? false{
            return false
        }
        return true
    }
    
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask{
        return .all
    }
    override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
        
        if let vplc = previewLayer.videoPreviewLayer.connection {
            
            let dot = UIDevice.current.orientation
            
            guard let newdot = AVCaptureVideoOrientation.init(rawValue: dot.rawValue), dot.isPortrait || dot.isLandscape else{
                return
            }
            super.willTransition(to: newCollection, with: coordinator)
            vplc.videoOrientation = newdot
        
        }
    }
    
    @objc fileprivate func segmentChage(segm: UISegmentedControl){
        if segm.selectedSegmentIndex == 0{
            captureBtn.backgroundColor = .red
            videCapture.changeToRecording()
        }
        else
        {
            captureBtn.backgroundColor = .white
            videCapture.changeToCapturePhoto()
        }
    }
    
    @objc fileprivate func captureClick(){
        if live.selectedSegmentIndex == 0{
            captureBtn.isEnabled = false
            live.isEnabled = false
            videCapture.startRecording(videoOrientation: previewLayer.videoPreviewLayer.connection!.videoOrientation, delegate: self)
        }
        else
        {
            videCapture.capturePhoto(videoOrientation: previewLayer.videoPreviewLayer.connection!.videoOrientation, delegate: self)
        }
    }
    
    @objc fileprivate func changeCamera(){
        videCapture.changeCamera()
    }
}

extension ViewController: AVCapturePhotoCaptureDelegate{
    
    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        guard error == nil else {return}
        photoData = photo.fileDataRepresentation()
    }
    
    func photoOutput(_ output: AVCapturePhotoOutput, didFinishCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?) {
        
        guard error == nil else {return}
        
        guard let photoData = photoData else {return}
        
        PHPhotoLibrary.requestAuthorization { (status) in
            if status == .authorized {
                
                PHPhotoLibrary.shared().performChanges {
                    
                    let options = PHAssetResourceCreationOptions()
                    let createRequest = PHAssetCreationRequest.forAsset()
                    options.uniformTypeIdentifier = self.requestedPhotoSettings.processedFileType.map({ $0.rawValue})
                    createRequest.addResource(with: .photo, data: photoData, options: options)
                    DispatchQueue.main.async {
                        self.photoImageBtn.setBackgroundImage(UIImage.init(data: photoData), for: .normal)
                    }
                } completionHandler: { (_, error) in
                    
                }
            }
        }
    }
}

extension ViewController: AVCaptureFileOutputRecordingDelegate{
    
    func fileOutput(_ output: AVCaptureFileOutput, didStartRecordingTo fileURL: URL, from connections: [AVCaptureConnection]) {
        DispatchQueue.main.async {
            self.captureBtn.isEnabled = true
            self.captureBtn.backgroundColor = .orange
            self.live.isEnabled = true
        }
    }
    
    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
        
        func cleanup(){
            let path = outputFileURL.path
            if FileManager.default.fileExists(atPath: path){
                
                do {
                    try FileManager.default.removeItem(atPath: path)
                } catch  {
                }
            }
            if let currentBackgroundId = videCapture.backgroundRecordingID{
                videCapture.backgroundRecordingID = UIBackgroundTaskIdentifier.invalid
                
                if currentBackgroundId != UIBackgroundTaskIdentifier.invalid{
                    UIApplication.shared.endBackgroundTask(currentBackgroundId)
                }
            }
        }
        
        var success = true
        
        if error != nil {
            success = (((error! as NSError).userInfo[AVErrorRecordingSuccessfullyFinishedKey] as AnyObject).boolValue)!
        }
        
        if success {
            
            PHPhotoLibrary.requestAuthorization { (status) in
                if status == .authorized {
                    PHPhotoLibrary.shared().performChanges {
                        let options = PHAssetResourceCreationOptions()
                        options.shouldMoveFile = true
                        let creationRequest = PHAssetCreationRequest.forAsset()
                        creationRequest.addResource(with: .video, fileURL: outputFileURL, options: options)
                    } completionHandler: { (success, error) in
                        cleanup()
                    }
                }
                else
                {
                    cleanup()
                }
            }
        }
        else
        {
            cleanup()
        }
        DispatchQueue.main.async {
            self.captureBtn.isEnabled = true
            self.captureBtn.backgroundColor = .red
            self.live.isEnabled = true
        }
    }
}
